package com.lf2.util;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileUtils {
	private final static String TAG = "ScanDecoder_FileUtils";
	private final static String IMG_SAVE_PATH = "/ScanPreview/";
	private final static String IMAGE_FILE_NAME_FORMAT = "yyyyMMdd_HHmmssSSS";
	
	private final static String SD_PATH = Environment.getExternalStorageDirectory().toString();

	private final static String RESULT_SAVE_PATH = "/DecodeResult/";
	private final static String RESULT_FILE_NAME = "DecodeResult.txt";
	
	private final static String LANDI_DECODE_CERTIFICATION_DIR = "LandiDecodeCert";
	
	public static void saveBitmap_pngFormat(Bitmap bitmap, String dir) {
		String path = SD_PATH+ IMG_SAVE_PATH + dir + "/";
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		SimpleDateFormat mFormat = new SimpleDateFormat(IMAGE_FILE_NAME_FORMAT);
		Date date = new Date(System.currentTimeMillis());
		String title = mFormat.format(date);
		
		File file = new File(path, title + ".png");
		OutputStream fOut = null;
		try {
			fOut = new FileOutputStream(file);
			//bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut);//jpg格式，压缩率85，即压缩15%
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);//PNG格式，PNG是无损的，即压缩，第二个参数在PNG格式下是无效的可以随便设置
			fOut.flush();
		} catch (Exception e) {
			LogUtils.e(TAG, "save image fail: " + e);
		} finally {
			try {
				if (fOut != null) {
					fOut.close();
				}
			} catch (IOException e) {
			}
		}
	}
	/*
	public static void saveBitmap_bmpFormat(Bitmap bitmap,String dir) {
		String path = SD_PATH+ IMG_SAVE_PATH + dir + "/";
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		SimpleDateFormat mFormat = new SimpleDateFormat(IMAGE_FILE_NAME_FORMAT);
		Date date = new Date(System.currentTimeMillis());
		String title = mFormat.format(date);
		
		File file = new File(path, title + ".bmp");
		OutputStream fOut = null;
		try {
			fOut = new FileOutputStream(file);
			byte[] buffer = bmpUtil.bitmap2BmpBytes(bitmap);
			fOut.write(buffer);
			fOut.flush();
		} catch (Exception e) {
			LogUtils.e(TAG, "save image fail: " + e);
		} finally {
			try {
				if (fOut != null) {
					fOut.close();
				}
			} catch (IOException e) {
			}
		}
	}
	
	public static void saveBitmap_absulutePath_bmpFormat(Bitmap bitmap,String dir, String name) {
		String path = dir + "/";
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		
		String title = name;
		
		File file = new File(path, title + ".bmp");
		OutputStream fOut = null;
		try {
			fOut = new FileOutputStream(file);
			byte[] buffer = bmpUtil.bitmap2BmpBytes(bitmap);
			fOut.write(buffer);
			fOut.flush();
		} catch (Exception e) {
			LogUtils.e(TAG, "save image fail: " + e);
		} finally {
			try {
				if (fOut != null) {
					fOut.close();
				}
			} catch (IOException e) {
			}
		}
	}
	*/
	public static void saveRawImg(byte[] imgBuf, String dir, int width, int height, int imgSize) {
		String path = SD_PATH+ IMG_SAVE_PATH + dir + "/";
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		SimpleDateFormat mFormat = new SimpleDateFormat(IMAGE_FILE_NAME_FORMAT);
		Date date = new Date(System.currentTimeMillis());
		String title = mFormat.format(date);
		
		byte[] buffer = new byte[imgSize];
		for(int i=0;i<imgSize;i++)
			buffer[i] = imgBuf[i];
		
		File file = new File(path, title + "_"+width+"x"+height+".raw");
		OutputStream fOut = null;
		try {
			fOut = new FileOutputStream(file);
			fOut.write(buffer);
			fOut.flush();
		} catch (Exception e) {
			LogUtils.e(TAG, "save image fail: " + e);
		} finally {
			try {
				if (fOut != null) {
					fOut.close();
				}
			} catch (IOException e) {
			}
		}
	}
	
	public static void saveRawImg_absulutePath(byte[] imgBuf, String dir, String name, int width, int height, int imgSize) {
		String path = dir + "/";
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		
		String title = name;
		
		byte[] buffer = new byte[imgSize];
		for(int i=0;i<imgSize;i++)
			buffer[i] = imgBuf[i];
		
		File file = new File(path, title + ".raw");
		OutputStream fOut = null;
		try {
			fOut = new FileOutputStream(file);
			fOut.write(buffer);
			fOut.flush();
		} catch (Exception e) {
			LogUtils.e(TAG, "save image fail: " + e);
		} finally {
			try {
				if (fOut != null) {
					fOut.close();
				}
			} catch (IOException e) {
			}
		}
	}

	public static void saveDecodeMsgToFile(boolean isDecoding, int totalTimes,int succTimes,int failTimes){
		String path = SD_PATH + RESULT_SAVE_PATH;
		File savedDir = new File(path);
		if (!savedDir.exists()) {
			savedDir.mkdirs();
		}
		
		File file = new File(path, RESULT_FILE_NAME);
		String outStr = null;
		/**第一次创建*/
		if (!file.exists()){
			try {
				file.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			outStr = String.format("\t\t\t\t%s\t\t%s\t\t%s\t\t%s", "Time","TotalDecode","SuccDecode","FailDecode");
		}else{
			if (isDecoding == false){
				return;
			}
			SimpleDateFormat mFormat = new SimpleDateFormat(IMAGE_FILE_NAME_FORMAT);
			Date date = new Date(System.currentTimeMillis());
			String time = mFormat.format(date);
			outStr = String.format("%s\t\t%d\t\t\t\t\t%d\t\t\t\t\t\t%d", time,totalTimes,succTimes,failTimes);
		}
		
		FileWriter fw;
		BufferedWriter bw;
		try {
			fw = new FileWriter(file, true);
			bw = new BufferedWriter(fw);
			bw.write(outStr);
			bw.newLine();
			bw.flush(); //将数据更新至文件
			bw.close();
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
	}
	
	@TargetApi(Build.VERSION_CODES.GINGERBREAD)
	@SuppressLint("NewApi")
	public static String creatDecodeCertificationDir(Context context){
		String path=null;
		if (Environment.getExternalStorageState().equals(
		            Environment.MEDIA_MOUNTED)) {
			LogUtils.d(TAG, "has ExternalStorage");
			path = Environment.getExternalStorageDirectory()
			          .getAbsolutePath() + File.separator + LANDI_DECODE_CERTIFICATION_DIR;
		} else {
			LogUtils.d(TAG, "not ExternalStorage, set cer dir to apk dir");
			path = context.getFilesDir().getAbsolutePath()  
		            + File.separator + LANDI_DECODE_CERTIFICATION_DIR;
		}  
		LogUtils.d(TAG, LANDI_DECODE_CERTIFICATION_DIR + " path="+path);
		File file = new File(path);
		if (!file.exists()) { 
			LogUtils.d(TAG, "dir not exist, creat a new dir");
		    file.mkdirs();  
		}else{
			LogUtils.d(TAG, "dir exist");
		}
		boolean ret = file.setReadable(true);
		if(ret==true){
			LogUtils.d(TAG, "set file readable success");
		}else{
			LogUtils.d(TAG, "set file readable failed");
		}
		ret = file.setWritable(true);
		if(ret==true){
			LogUtils.d(TAG, "set file Writable success");
		}else{
			LogUtils.d(TAG, "set file Writable failed");
		}
		return path;
	}
	
	/*********************
	 * return:
	 * 	>0 actual read len
	 * 	0  no data read 
	 * 	-1 File Not Found
	 * 	-2 IOException
	 * 	-3 file size!=readLen
	 * *******************/
	public static byte[] readFile(String path){
		Log.i(TAG, Util.getMethodLine()+"filePath="+path);
		FileInputStream is;
		//int ret=0;
		
		try {
			is = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"File Not Found");
			return null;
		}  
		
		int size=0;
		try {
			size = is.available();
		} catch (IOException e) {
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in available()");
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			} 
			return null;
		}
		if(size==0){
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			} 
			return null;
		}
		byte[] rawFileData = new byte[size];
		int readLen = 0;
		try {
			readLen = is.read(rawFileData);
		} catch (IOException e2) {
			e2.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in read");
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			}
			return null;
		}
			
		if(readLen!=size){		
			Log.i(TAG, Util.getMethodLine()+"file size!=readLen"+",fileSize="+size+",readLen="+readLen);
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			}
			return null;
		}
		try {
			is.close();
		} catch (IOException e1) {
			e1.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in close");
			return null;
		}
		
    	return rawFileData;  	
    }
	
	/*********************
	 * return:
	 * 	>0 actual read len
	 * 	0  no data read 
	 * 	-1 File Not Found
	 * 	-2 IOException
	 * 	-3 file size!=readLen
	 * *******************/
	public static int readFile(String path, byte[] data, int len){
		Log.i(TAG, Util.getMethodLine()+"filePath="+path);
		FileInputStream is;
		int ret=0;
		
		try {
			is = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"File Not Found");
			ret = -1;//File Not Found	
			return ret;
		}  
		
		int size=0;
		try {
			size = is.available();
		} catch (IOException e) {
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in available()");
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			} 
			ret = -2;//IOException
			return ret;
		}
		if(size==0){
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			} 
			ret = 0;//no data in file
			return ret;
		}
		byte[] rawFileData = new byte[size];
		int readLen = 0;
		try {
			readLen = is.read(rawFileData);
		} catch (IOException e2) {
			e2.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in read");
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			}
			ret = -2;//IOException
			return ret;
		}
			
		if(readLen!=size){		
			Log.i(TAG, Util.getMethodLine()+"file size!=readLen"+",fileSize="+size+",readLen="+readLen);
			try {
				is.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				Log.i(TAG, Util.getMethodLine()+"IOException in close");
			}
			ret = -3;//file size!=readLen
			return ret;
		}
		try {
			is.close();
		} catch (IOException e1) {
			e1.printStackTrace();
			Log.i(TAG, Util.getMethodLine()+"IOException in close");
			ret = -2;//IOException in close
			return ret;
		}
		
		if(readLen<len)
			ret = readLen;
		else
			ret = len;
		for(int i=0;i<ret;i++)
			data[i] = rawFileData[i];
    	return ret;  	
    }

	/*********************
	 * return:
	 * 	>0 actual read len
	 * 	-1 IOException
	 * 	-2 file not exist
	 * *******************/
	public static int writeFile(String path, byte[] data, int len, boolean ifNoExistCreate){
		Log.i(TAG, Util.getMethodLine() + "filePath="+ path);
		char[] writeData= new char[len];
		for(int i=0;i<len;i++){
			writeData[i] = (char)(data[i]&0xff);
		}
		
		File file = new File(path);
		if (!file.exists()){
			if(ifNoExistCreate==true){
				Log.i(TAG, Util.getMethodLine() + path + " not exist, create it");
				try {
					file.createNewFile();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					Log.i(TAG, Util.getMethodLine() + "createNewFile IOException");
					return -1;
				}
			}else{
				return -2;
			}
			
		}else{
			Log.i(TAG, Util.getMethodLine() + path + " exist, use it");
		}
		
		chmod(path);
		
		FileWriter fw=null;
		BufferedWriter bw=null;
		
		try {
			fw = new FileWriter(file, false);//每次从文件头开始写
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine() + "new FileWriter IOException");
			return -1;
		}
		
		bw = new BufferedWriter(fw);
		
		try {
			bw.write(writeData,0,len);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine() + "bw.write IOException");
			try {
				bw.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				Log.i(TAG, Util.getMethodLine() + "bw.close IOException");
			}
			try {
				fw.close();
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				Log.i(TAG, Util.getMethodLine() + "fw.close IOException");
			}
			return -1;
		}
		
		try {
			bw.flush();//将数据更新至文件
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine() + "bw.flush IOException");
			try {
				bw.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				Log.i(TAG, Util.getMethodLine() + "bw.close IOException");
			}
			try {
				fw.close();
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				Log.i(TAG, Util.getMethodLine() + "fw.close IOException");
			}
			return -1;
		} 

		try {
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine() + "bw.close IOException");
		}
		try {
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.i(TAG, Util.getMethodLine() + "fw.close IOException");
		}
		return len;
	}
	
	public static void chmod(String Path)
	{
		Process p;
		int status = -1;  
		try {  
		    p = Runtime.getRuntime().exec("chmod 777 " + Path);
		    status = p.waitFor();  
		} catch (IOException e) {
		    // TODO Auto-generated catch block  
		    e.printStackTrace();  
		} catch (InterruptedException e) {
		    // TODO Auto-generated catch block  
		    e.printStackTrace();  
		}  
		if(status == 0){       
			Log.i(TAG, Util.getMethodLine() + "chmod succeed");
		}else {      
			Log.i(TAG, Util.getMethodLine() + "chmod failed");
		}  
		
	}
	
}

